package com.zwh.se.collection.map;

/**
 * @author yexi
 *
 * 说了那么多的hash,那么各种数据类型的哈希值到底是怎么计算出来的呢?
 * 这里就展示一下底层对各个类型的hash算法
 */
public class HashCodeDemo {
    public static void main(String[] args) {
        System.out.println("----------int的hash值就是它本身----------");
        //return value;
        Integer val = new Integer(1);
        int hash = val.hashCode();
        System.out.println(hash);

        System.out.println("----------float的hash就是把它的整数位和小数位直接硬拼起来,变为一个32位的int," +
                "再求出hash值(无视整数位小数位把它当作了一个32位int来看)----------");
        //由于整数位在小数位很靠前的位置,所以即便只是一个1,都已经是个很大的数值了
        //return floatToRawIntBits(value);
        Float aFloat = new Float(1.0f);
        System.out.println(aFloat.hashCode());

        System.out.println("----------long的hash,则是取低位,跟原值异或取结果,强转丢精度,获得最后的结果----------");
        //return (int)(value ^ (value >>> 32));
        Long aLong = new Long(1L);
        System.out.println(aLong.hashCode());

        System.out.println("----------double的hash,跟float一样逻辑,把double变成long,然后逻辑跟Long一样----------");
        Double aDouble = new Double(1.0f);
        System.out.println(aDouble.hashCode());

        System.out.println("----------String的hash,详情看方法----------");
        String asd = new String("asd");
        stringHashCode(asd);
        //而比较自定义对象时,我们就用人为的业务认识来重写hashcode了,一般会将对象中所有字段都作为hash计算的一部分来计算

    }

    /**
     * 模仿真实字符串求hash值底层写的(jdk1.8版本)(注意,由于底层操作涉及字段所以并不是完全一致的,只是做参考)
     * @param string 传入的字符串
     */
    public static void stringHashCode(String string) {
        int hashCode = 0;
        int len = string.length();
        for (int i = 0; i < len; i++) {
            char c = string.charAt(i);
            hashCode = 31 * hashCode + c;
        }
        System.out.println(hashCode);
        System.out.println(string.hashCode());
    }

    //↓下面是jdk11版本的
    /*        public int hashCode () {
            int h = hash;
            if (h == 0 && value.length > 0) {
                hash = h = isLatin1() ? StringLatin1.hashCode(value)
                        : StringUTF16.hashCode(value);
            }
            return h;
        }

        //StringLatin1
        //为什么使用31,31是奇素数,统计表明使用这个奇素数能让哈希分布更均匀,JVM会将31*h优化成(h<<5)-h
        public static int hashCode (byte[] value){
            int h = 0;
            for (byte v : value) {
                h = 31 * h + (v & 0xff);
            }
            return h;
        }

        //StringUTF16
        public static int hashCode (byte[] value){
            int h = 0;
            int length = value.length >> 1;
            for (int i = 0; i < length; i++) {
                h = 31 * h + getChar(value, i);
            }
            return h;
        }*/

}
